{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# DEBUGGING TIMESKETCH API WITH PYTHON"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook can be used to debug Timesketch: it can create/delete/visualize sketches and timelines, retrieve analyzers' results, run queries on a sketch and many others. Feel free to use and modify the section that you find more useful."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -q timesketch_api_client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "from timesketch_api_client import config\n",
    "from timesketch_api_client import sketch\n",
    "from timesketch_api_client import timeline\n",
    "from timesketch_api_client import analyzer\n",
    "from timesketch_api_client import search\n",
    "\n",
    "from timesketch_import_client import helper\n",
    "from timesketch_import_client import importer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialization section\n",
    "Define here the name of the sketch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketch_name = \"foobar\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ts_client = config.get_client()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GET section\n",
    "This section has the command to retrieve the list of sketches, timelines, analyzers..."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET list of sketches"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches()]\n",
    "for sketch in sketches:\n",
    "    print(f\"Sketch name: {sketch[1]} ({sketch[0]})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET list of sketch - timeline - datasource"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches()]\n",
    "for sketch_info in sketches:\n",
    "    try:\n",
    "        sketch = ts_client.get_sketch(sketch_info[0])\n",
    "        print(f\"[S] {sketch.name} ({sketch.id})\")\n",
    "        for timeline in sketch.list_timelines():\n",
    "            print(f\"   - [T] {timeline.name} ({timeline.id})\")\n",
    "            for datasource in timeline.data_sources:\n",
    "                print(f\"      - [D] {datasource['context']} ({datasource['status'][0]['status']})\")\n",
    "    except Exception as e:\n",
    "        print(f\"[S]{sketch_info[1]} ({sketch_info[0]}) skipped\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET detailed events of a sketch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketch_ID = 1\n",
    "print(f\"Using sketch ID {sketch_ID}\")\n",
    "sketch = ts_client.get_sketch(sketch_ID)\n",
    "print(json.dumps(sketch.data, indent=4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET detailed events of a timeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "timeline_ID = 12\n",
    "\n",
    "# first need to find the sketch of that timeline\n",
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches()]\n",
    "for sketch_info in sketches:\n",
    "    try:\n",
    "        sketch = ts_client.get_sketch(sketch_info[0])\n",
    "        timelines_ID = [x.id for x in sketch.list_timelines()]\n",
    "        if timeline_ID in timelines_ID:\n",
    "            print(f\"Found timeline ID {timeline_ID} in sketch {sketch_info[1]}\")\n",
    "            print(f\"Print information of timeline ID {timeline_ID}...\")\n",
    "            timeline_info = sketch.get_timeline(timeline_ID).data\n",
    "            print(json.dumps(timeline_info, indent=4))\n",
    "            break\n",
    "    except Exception as e:\n",
    "        print(f\"Cannot retrieve timeline ID {timeline_id}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET events by running a QUERY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketch_ID = 1\n",
    "screenshot_events = None\n",
    "\n",
    "try:\n",
    "    sketch = ts_client.get_sketch(sketch_ID)\n",
    "    query = ('*')\n",
    "\n",
    "    search_obj = search.Search(sketch)\n",
    "\n",
    "    search_obj.query_string = query\n",
    "    screenshot_events = search_obj.table\n",
    "except Exception as e:\n",
    "    print(f\"Cannot find sketch ID {sketch_ID}\")\n",
    "\n",
    "print(f\"Query: {query}\")\n",
    "screenshot_events"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CREATE section\n",
    "In this section the are commands to create new sketch, a single timeline, a single timeline with multiple datasource and multiple timelines."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create a new sketch (if the name is unique)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(\"Sketch already exists\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "else:\n",
    "    print(\"Create new sketch\")\n",
    "    sketch = ts_client.create_sketch(name=sketch_name)\n",
    "\n",
    "sketch_ID = sketch.id\n",
    "print(f\"Sketch information: {sketch.name} ({sketch_ID})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create new timeline given a sketch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = \"/tmp/sample_chrome_logs.plaso\"\n",
    "timeline_name = \"_\".join(filename.split(\"/\")[-1].split(\".\")[:-1])\n",
    "\n",
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(f\"Using sketch {sketch_name}\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "    import_helper = helper.ImportHelper() \n",
    "    with importer.ImportStreamer() as streamer:\n",
    "        streamer.set_sketch(sketch)\n",
    "        streamer.set_config_helper(import_helper)\n",
    "        streamer.set_timeline_name(timeline_name)\n",
    "        streamer.add_file(filename)\n",
    "        print(f\"Timeline {timeline_name} inserted\")\n",
    "else:\n",
    "    print(\"No sketch with that name\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create timelines given a list of files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# feel free to modify these lines as they are only used to fill the array list_files\n",
    "import os\n",
    "dir_path = r'/tmp/list_files'\n",
    "\n",
    "# list to store files\n",
    "list_files = []\n",
    "\n",
    "# Iterate directory\n",
    "for path in os.listdir(dir_path):\n",
    "    # check if current path is a file\n",
    "    if os.path.isfile(os.path.join(dir_path, path)):\n",
    "        list_files.append(dir_path + '/' + path)\n",
    "print(f\"List of files: {', '.join(list_files)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(f\"Using sketch {sketch_name}\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "    import_helper = helper.ImportHelper()     \n",
    "    for filename in list_files:\n",
    "        timeline_name = \"_\".join(filename.split(\"/\")[-1].split(\".\")[:-1])\n",
    "        try:\n",
    "            with importer.ImportStreamer() as streamer:\n",
    "                streamer.set_sketch(sketch)\n",
    "                streamer.set_config_helper(import_helper)\n",
    "                streamer.set_timeline_name(timeline_name)\n",
    "                streamer.add_file(filename)\n",
    "                print(f\"Timeline {timeline_name} inserted\")\n",
    "        except Exception as e:\n",
    "            print(f\"{filename} skipped\")\n",
    "else:\n",
    "    print(f\"no sketch found with name {sketch_name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create a manual event"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "datetime = \"2020-08-06T12:48:06.994188Z\"\n",
    "message = \"only a test to insert a manual event v2\"\n",
    "timestamp_desc = \"creation time\"\n",
    "attributes = {\"a\": \"alpha\", \"o\": \"omega\", \"g\": \"gamma\"}\n",
    "tags = [\"this\", \"field\", \"is\", \"optional\",]\n",
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(f\"Using sketch {sketch_name}\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "    sketch.add_event(message, datetime, timestamp_desc, attributes, tags)\n",
    "    print(\"Manual event added\")\n",
    "else:\n",
    "    print(f\"no sketch found with name {sketch_name}\")    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DELETE section"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Delete one or more timelines in the sketch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "timeline_names = [\"ac01-chrome-history\"]\n",
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(f\"Using sketch {sketch_name}\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "    for timeline_name in timeline_names:\n",
    "        timeline = sketch.get_timeline(timeline_name=timeline_name)\n",
    "        if timeline:\n",
    "            timeline.delete()\n",
    "            print(f\"Timeline {timeline_name} deleted\")\n",
    "        else:\n",
    "            print(f\"Timeline {timeline_name} not found\")\n",
    "else:\n",
    "    print(f\"no sketch found with name {sketch_name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Delete all the timelines in the sketch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches() if x.name == sketch_name]\n",
    "sketch = None\n",
    "if sketches:\n",
    "    print(f\"Using sketch {sketch_name}\")\n",
    "    sketch = ts_client.get_sketch(sketches[0][0])\n",
    "    timelines = sketch.list_timelines()\n",
    "    for timeline in timelines:\n",
    "        try:\n",
    "            timeline_name = timeline.name\n",
    "            timeline.delete()\n",
    "            print(f\"Timeline {timeline_name} deleted\")\n",
    "        except Exception as e:\n",
    "            print(f\"ERROR: Timeline {timeline_name} skipped\")\n",
    "else:\n",
    "    print(f\"no sketch found with name {sketch_name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ANALYZER Section\n",
    "In this section the user can list and run the analyzers available on Timesketch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GET list of available analyzers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sketch_ID = 1\n",
    "print(f\"Listing analyzers available for sketch ID {sketch_ID}\")\n",
    "for list_analyzers in ts_client.get_sketch(sketch_ID).list_available_analyzers():\n",
    "    print(json.dumps(list_analyzers, indent=4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Retrieve the result of an analyzer\n",
    "Retrieve the results of an analyzer given a timeline ID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "analyzer_name = \"domain\"\n",
    "timeline_ID = 12\n",
    "sketches = [(x.id, x.name) for x in ts_client.list_sketches()]\n",
    "for sketch_info in sketches:\n",
    "    try:\n",
    "        sketch = ts_client.get_sketch(sketch_info[0])\n",
    "        timelines_ID = [x.id for x in sketch.list_timelines()]\n",
    "        if timeline_ID in timelines_ID:\n",
    "            print(f\"Found timeline ID {timeline_ID} in sketch {sketch_info[1]}\")\n",
    "            print(f\"Run anylyzer {analyzer_name} for timeline ID {timeline_ID}...\")\n",
    "            timeline = sketch.get_timeline(timeline_ID)\n",
    "            analyzer = timeline.run_analyzer(analyzer_name=analyzer_name, ignore_previous=True)\n",
    "            print(\"Run below cells to get the analyzer's result\")\n",
    "            break\n",
    "    except Exception as e:\n",
    "        print(f\"Cannot run analyzer on timeline ID {timeline_ID}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "all_results = [x._fetch_data() for x in analyzer]\n",
    "all_results"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
